/**
 * Copyright (C), 2015-2020, XXX有限公司
 * FileName: ComprehensiveScoreServiceImpl
 * Author:   智勇
 * Date:     2020/3/5 22:35
 * Description: 综合测评service
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.night.icm.service.base.service.comprehensive_test;

import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.night.icm.common.exception.NoSuchDataException;
import com.night.icm.common.night_enum.CompAssessProcessStatus;
import com.night.icm.model.base.comprehensive_test.ComprehensiveScoreDTO;
import com.night.icm.persistence.base.entity.Academy;
import com.night.icm.persistence.base.entity.Class;
import com.night.icm.persistence.base.entity.Profession;
import com.night.icm.persistence.base.entity.Student;
import com.night.icm.persistence.base.entity.comprehensive_test.AcademicPoint;
import com.night.icm.persistence.base.entity.comprehensive_test.ComprehensiveScore;
import com.night.icm.persistence.base.entity.comprehensive_test.IdeologicalPoint;
import com.night.icm.persistence.base.entity.comprehensive_test.StylisticPoint;
import com.night.icm.persistence.base.repository.comprehensive_test.ComprehensiveScoreRepository;
import com.night.icm.persistence.business.entity.ConsolidatedResults;
import com.night.icm.persistence.business.reporsitory.ConsolidatedResultsRepository;
import com.night.icm.service.base.mapper.comprehensive_test.ComprehensiveScoreMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * ComprehensiveScoreServiceImpl
 * 〈综合测评service〉
 *
 * @author 智勇
 * @create 2020/3/5
 * @since 1.0.0
 */
@Slf4j
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
public class ComprehensiveScoreServiceImpl implements ComprehensiveScoreService{

    private final ComprehensiveScoreRepository comprehensiveScoreRepository;
    private final ComprehensiveScoreMapper comprehensiveScoreMapper;
    private final StylisticPointService stylisticPointService;
    private final AcademicPointService academicPointService;
    private final IdeologicalPointService ideologicalPointService;
    private final ConsolidatedResultsRepository consolidatedResultsRepository;

    @Autowired
    public ComprehensiveScoreServiceImpl(ComprehensiveScoreRepository comprehensiveScoreRepository, ComprehensiveScoreMapper comprehensiveScoreMapper, StylisticPointService stylisticPointService, AcademicPointService academicPointService, IdeologicalPointService ideologicalPointService, ConsolidatedResultsRepository consolidatedResultsRepository) {
        this.comprehensiveScoreRepository = comprehensiveScoreRepository;
        this.comprehensiveScoreMapper = comprehensiveScoreMapper;
        this.stylisticPointService = stylisticPointService;
        this.academicPointService = academicPointService;
        this.ideologicalPointService = ideologicalPointService;
        this.consolidatedResultsRepository = consolidatedResultsRepository;
    }

    /**
     * 查找学生综合测评
     *
     * @param studentId               学生id
     * @param compAssessProcessStatus 流程状态
     * @return 学生综合测评
     */
    @Override
    public List<ComprehensiveScoreDTO> findAll(String studentId, CompAssessProcessStatus compAssessProcessStatus) {
        PredicateBuilder<ComprehensiveScore> pb = Specifications.<ComprehensiveScore>and()
                .eq(StringUtils.isNotBlank(studentId), "student.id", studentId)
                .eq(compAssessProcessStatus != null, "compAssessProcessStatus", compAssessProcessStatus);
        List<ComprehensiveScore> comprehensiveScores = this.comprehensiveScoreRepository.findAll(pb.build());
        return this.comprehensiveScoreMapper.toList(comprehensiveScores);
    }

    /**
     * 模糊查询学生综合测评
     *
     * @param academyName             所属学院name
     * @param professionName          所属专业name
     * @param className               所属班级name
     * @param studentName             学生学号name
     * @param year                    所属年度
     * @param compAssessProcessStatus 流程状态
     * @param classId                 班级id
     * @param studentId               学生id
     * @param studentCode             学生code
     * @return 学生综合测评
     */
    @Override
    public List<ComprehensiveScoreDTO> search(String academyName, String professionName, String className, String studentName, String year, CompAssessProcessStatus compAssessProcessStatus, String classId, String studentId, String studentCode) {
        Specification<ComprehensiveScore> specification = ((Root<ComprehensiveScore> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            List<Predicate> conditions = new ArrayList<>();
            if (!StringUtils.isAllBlank(academyName, professionName, className, studentName, year, classId, studentId, studentCode) || null != compAssessProcessStatus) {
                if (StringUtils.isNotBlank(year)) {
                    conditions.add(cb.and(cb.equal(root.get("year").as(Integer.class), Integer.valueOf(year))));
                }
                if (null != compAssessProcessStatus) {
                    conditions.add(cb.and(cb.equal(root.get("compAssessProcessStatus").as(CompAssessProcessStatus.class), compAssessProcessStatus)));
                }
                Join<ComprehensiveScore, Student> studentJoin = root.join("student", JoinType.LEFT);
                Join<Student, Academy> academyJoin = studentJoin.join("academy", JoinType.LEFT);
                Join<Student, Profession> professionJoin = studentJoin.join("profession", JoinType.LEFT);
                Join<Student, Class> classJoin = studentJoin.join("aClass", JoinType.LEFT);
                if (StringUtils.isNotBlank(academyName)) {
                    conditions.add(cb.and(cb.like(academyJoin.get("name").as(String.class), "%" + academyName + "%")));
                }
                if (StringUtils.isNotBlank(professionName)) {
                    conditions.add(cb.and(cb.like(professionJoin.get("name").as(String.class), "%" + professionName + "%")));
                }
                if (StringUtils.isNotBlank(className)) {
                    conditions.add(cb.and(cb.like(classJoin.get("name").as(String.class), "%" + className + "%")));
                }
                if (StringUtils.isNotBlank(classId)) {
                    conditions.add(cb.and(cb.equal(classJoin.get("id").as(Long.class), Long.valueOf(classId))));
                }
                if (StringUtils.isNotBlank(studentName)) {
                    conditions.add(cb.and(cb.like(studentJoin.get("name").as(String.class), "%" + studentName + "%")));
                }
                if (StringUtils.isNotBlank(studentCode)) {
                    conditions.add(cb.and(cb.like(studentJoin.get("code").as(String.class), "%" + studentCode + "%")));
                }
                if (StringUtils.isNotBlank(studentId)) {
                    conditions.add(cb.and(cb.equal(studentJoin.get("id").as(Long.class), Long.valueOf(studentId))));
                }
            }
            if (!conditions.isEmpty()) {
                query.where(conditions.toArray(new Predicate[0]));
            }
            return null;
        });
        List<ComprehensiveScore> comprehensiveScores = this.comprehensiveScoreRepository.findAll(specification);
        return this.comprehensiveScoreMapper.toList(comprehensiveScores);
    }

    /**
     * 新建年度综合测评
     * 由于已存在草稿状态的综合分，此方法用于新建自评、班评、年级评审、公示结果数据
     *
     * @param comprehensiveScoreDTO 综合测评信息
     * @return 综合测评信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ComprehensiveScoreDTO create(ComprehensiveScoreDTO comprehensiveScoreDTO) {
        ComprehensiveScore comprehensiveScore = this.comprehensiveScoreMapper.toEntity(comprehensiveScoreDTO);
        ComprehensiveScore one = this.comprehensiveScoreRepository.getOne(comprehensiveScore.getId());
        Student student = one.getStudent();
        // id置空，意为新建流程为下一阶段的综合测评数据
        comprehensiveScore.setId(null);
        comprehensiveScore.setStudent(student);
        comprehensiveScore.setIsReport(false);
        this.comprehensiveScoreRepository.save(comprehensiveScore);
        // 保存关联的学业分及其附件
        if (comprehensiveScoreDTO.getAcademicPoint() != null) {
            comprehensiveScoreDTO.getAcademicPoint().setId(null);
            AcademicPoint academicPoint = this.academicPointService.create(comprehensiveScoreDTO.getAcademicPoint(), comprehensiveScore);
            comprehensiveScore.setAcademicPoint(academicPoint);
            this.comprehensiveScoreRepository.save(comprehensiveScore);
        }
        // 保存关联的思想分及其附件
        if (comprehensiveScoreDTO.getIdeologicalPoint() != null) {
            comprehensiveScoreDTO.getIdeologicalPoint().setId(null);
            IdeologicalPoint ideologicalPoint = this.ideologicalPointService.create(comprehensiveScoreDTO.getIdeologicalPoint(), comprehensiveScore);
            comprehensiveScore.setIdeologicalPoint(ideologicalPoint);
            this.comprehensiveScoreRepository.save(comprehensiveScore);
        }
        // 保存关联的文体分及其附件
        if (comprehensiveScoreDTO.getStylisticPoint() != null) {
            comprehensiveScoreDTO.getStylisticPoint().setId(null);
            StylisticPoint stylisticPoint = this.stylisticPointService.create(comprehensiveScoreDTO.getStylisticPoint(), comprehensiveScore);
            comprehensiveScore.setStylisticPoint(stylisticPoint);
            this.comprehensiveScoreRepository.save(comprehensiveScore);
        }
        // 如果新建数据的流程状态为审结DONE_CLOSE，则添加到学生综合成绩中，用于学生综合成绩的统计分析
        if (comprehensiveScore.getCompAssessProcessStatus().equals(CompAssessProcessStatus.DONE_CLOSE)) {
            ConsolidatedResults consolidatedResults = new ConsolidatedResults();
            consolidatedResults.setGrade(comprehensiveScore.getStudent().getGrade());
            consolidatedResults.setYear(comprehensiveScore.getYear());
            consolidatedResults.setStudentId(comprehensiveScore.getStudent().getId());
            consolidatedResults.setStudentCode(comprehensiveScore.getStudent().getCode());
            consolidatedResults.setStudentName(comprehensiveScore.getStudent().getName());
            consolidatedResults.setGender(comprehensiveScore.getStudent().getGender());
            consolidatedResults.setAcademyId(comprehensiveScore.getStudent().getAcademy().getId());
            consolidatedResults.setAcademyName(comprehensiveScore.getStudent().getAcademy().getName());
            consolidatedResults.setProfessionId(comprehensiveScore.getStudent().getProfession().getId());
            consolidatedResults.setProfessionName(comprehensiveScore.getStudent().getProfession().getName());
            consolidatedResults.setClassId(comprehensiveScore.getStudent().getAClass().getId());
            consolidatedResults.setClassName(comprehensiveScore.getStudent().getAClass().getName());
            consolidatedResults.setConsolidatedResult(comprehensiveScore.getComprehensiveScoreTotal());
            this.consolidatedResultsRepository.save(consolidatedResults);
        }
        return this.comprehensiveScoreMapper.toDTO(comprehensiveScore);
    }

    /**
     * 提交综合测评数据
     * 若各项分都未建立，则在此新建并保存
     *
     * @param id                    综合测评id
     * @param comprehensiveScoreDTO 综合测评信息
     * @return 综合测评信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ComprehensiveScoreDTO complete(String id, ComprehensiveScoreDTO comprehensiveScoreDTO) {
        Optional<ComprehensiveScore> comprehensiveScoreOptional = this.comprehensiveScoreRepository.findById(Long.valueOf(id));
        if (!comprehensiveScoreOptional.isPresent()) {
            throw new NoSuchDataException(id);
        }
        ComprehensiveScore comprehensiveScore = comprehensiveScoreOptional.get();
        this.comprehensiveScoreMapper.updateEntity(comprehensiveScoreDTO, comprehensiveScore);
        if (Boolean.TRUE.equals(comprehensiveScoreDTO.getIsApproval())) {
            // 送审进入下一流程，新建流程数据
            if (comprehensiveScoreDTO.getCompAssessProcessStatus().equals(CompAssessProcessStatus.SELF_ASSESSMENT)) {
                // 自评：进入自评尚未进入斑评可修改
                comprehensiveScoreDTO.setCompAssessProcessStatus(CompAssessProcessStatus.CLASS_ASSESSMENT);
            } else if (comprehensiveScoreDTO.getCompAssessProcessStatus().equals(CompAssessProcessStatus.CLASS_ASSESSMENT)) {
                // 班评：进入斑评后学生不可修改，学生综测管理员可录入斑评结果
                comprehensiveScoreDTO.setCompAssessProcessStatus(CompAssessProcessStatus.GRADE_REVIEW);
            } else if (comprehensiveScoreDTO.getCompAssessProcessStatus().equals(CompAssessProcessStatus.GRADE_REVIEW)) {
                // 年级复审：公示3天，学生综测管理员不可需改，管理员可修改
                comprehensiveScoreDTO.setCompAssessProcessStatus(CompAssessProcessStatus.DONE_ASSESSMENT);
            } else if (comprehensiveScoreDTO.getCompAssessProcessStatus().equals(CompAssessProcessStatus.DONE_ASSESSMENT)) {
                // 评审公示结果，结果已确定，任何人不可修改
                comprehensiveScoreDTO.setCompAssessProcessStatus(CompAssessProcessStatus.DONE_CLOSE);
            }
            // 保留原有流程数据，并更新流程为下一流程
            comprehensiveScore.setIsReport(true);
            this.comprehensiveScoreRepository.save(comprehensiveScore);
            // 建立新流程数据
            comprehensiveScoreDTO.setIsApproval(false);
            return this.create(comprehensiveScoreDTO);
        } else {
            // 仅修改
            this.comprehensiveScoreRepository.save(comprehensiveScore);
            // 更新学业分及其附件
            AcademicPoint academicPoint = this.academicPointService.update(comprehensiveScoreDTO.getAcademicPoint(), comprehensiveScore);
            comprehensiveScore.setAcademicPoint(academicPoint);
            this.comprehensiveScoreRepository.save(comprehensiveScore);
            // 更新思想分及其附件
            IdeologicalPoint ideologicalPoint = this.ideologicalPointService.update(comprehensiveScoreDTO.getIdeologicalPoint(), comprehensiveScore);
            comprehensiveScore.setIdeologicalPoint(ideologicalPoint);
            this.comprehensiveScoreRepository.save(comprehensiveScore);
            // 更新文体分及其附件
            StylisticPoint stylisticPoint = this.stylisticPointService.update(comprehensiveScoreDTO.getStylisticPoint(), comprehensiveScore);
            comprehensiveScore.setStylisticPoint(stylisticPoint);
            this.comprehensiveScoreRepository.save(comprehensiveScore);
            return this.comprehensiveScoreMapper.toDTO(comprehensiveScore);
        }
    }

    /**
     * 通过id查找综合测评信息
     *
     * @param id id
     * @return 综测信息
     */
    @Override
    public ComprehensiveScoreDTO findById(String id) {
        Optional<ComprehensiveScore> byId = this.comprehensiveScoreRepository.findById(Long.valueOf(id));
        if (!byId.isPresent()) {
            throw new NoSuchDataException(id);
        }
        return this.comprehensiveScoreMapper.toDTO(byId.get());
    }
}